﻿//
//
//  @ Project : AgriMarketSystem
//  @ Date : 18/10/2013
//  @ Author : NTT
//
//

using System.Collections.Generic;
using System.Linq;
using System;
using System.Net.Mail;
using System.Threading;
namespace AgriMarketService
{
    public class AgriMarket
    {
        #region Articles
        public Article GetAnArticleByArticleId(int articleId)
        {
            return Article.GetAnArticleByArticleId(articleId);
        }
        public List<Article> GetNewArticles()
        {
            return Article.GetAllNewArticles();
        }
        public List<Article> GetNewSellArticles()
        {
            return SellArticle.GetAllNewArticles();
        }
        public List<Article> GetNewSellArticles(int startedId, int count, bool isLess)
        {
            List<Article> sellArticlesList = SellArticle.GetAllNewArticles();
            List<Article> result = null;
            if (sellArticlesList.Count != 0)
            {
                if (isLess)
                {
                    result = (from tempSellArticle in sellArticlesList
                              where tempSellArticle.ArticleId < startedId
                              orderby tempSellArticle.ArticleId descending
                              select tempSellArticle).Take(count).ToList();
                }
                else
                {
                    result = (from tempSellArticle in sellArticlesList
                              where tempSellArticle.ArticleId > startedId
                              orderby tempSellArticle.ArticleId descending
                              select tempSellArticle).Take(count).ToList();
                }
            }
            return result;
        }
        public List<Article> GetNNewSellArticles(int count)
        {
            List<Article> sellArticlesList = SellArticle.GetAllNewArticles();
            List<Article> result = null;
            result = (from tempSellArticle in sellArticlesList
                      orderby tempSellArticle.PostedDate descending
                      select tempSellArticle).Take(count).ToList();
            return result;
        }
        public List<Article> GetNewBuyArticles()
        {
            return BuyArticle.GetAllNewArticles();
        }
        public List<Article> GetNNewBuyArticles(int count)
        {
            List<Article> buyArticlesList = BuyArticle.GetAllNewArticles();
            List<Article> result = null;
            result = (from tempBuyArticle in buyArticlesList
                      orderby tempBuyArticle.PostedDate descending
                      select tempBuyArticle).Take(count).ToList();
            return result;
        }
        public List<Article> GetNewBuyArticles(int startedId, int count, bool isLess)
        {
            List<Article> buyArticlesList = BuyArticle.GetAllNewArticles();
            List<Article> result = null;
            if (buyArticlesList.Count != 0)
            {
                if (isLess)
                {
                    result = (from tempBuyArticle in buyArticlesList
                              where tempBuyArticle.ArticleId < startedId
                              orderby tempBuyArticle.ArticleId descending
                              select tempBuyArticle).Take(count).ToList();
                }
                else
                {
                    result = (from tempBuyArticle in buyArticlesList
                              where tempBuyArticle.ArticleId > startedId
                              orderby tempBuyArticle.ArticleId
                              select tempBuyArticle).Take(count).ToList();
                }
            }
            return result;
        }
        public int AddArticle(Article newArticle)
        {
            return Article.AddNew(newArticle);
        }
        public int UpdateArticle(Article updatedArticle)
        {
            return Article.Update(updatedArticle);
        }
        public int DeleteArticleByArticleId(int deletedArticleId)
        {
            return Article.DeleteByArticleId(deletedArticleId);
        }
        #endregion
        #region Comments
        public List<ArticleComment> DisplayAllArticleCommentsByArticleId(int articleId)
        {
            return ArticleComment.GetAllCommentByArticleId(articleId);
        }
        public int AddCommentToArticle(ArticleComment newArticleComment)
        {
            return ArticleComment.AddNew(newArticleComment);
        }
        public int UpdateComment(ArticleComment updatedComment)
        {
            return ArticleComment.Update(updatedComment);
        }
        public int DeleteArticleCommentByArticleCommentId(int deletedArticleCommentId)
        {
            return ArticleComment.DeleteByArticleCommentId(deletedArticleCommentId);
        }
        public bool DeleteAllArticleCommentsByArticleId(int articleId)
        {
            return ArticleComment.DeleteAllCommentsByArticleId(articleId);
        }
        public List<ArticleComment> DisplayNNextArticleComments(int articleId, int startedArticleCommentId, int count)
        {
            return ArticleComment.GetNFirstArticleComments(articleId, startedArticleCommentId, count);
        }
        #endregion
        #region Auctions
        public List<Auction> GetNNewUnfinishedAuctions(int n)
        {
            List<Auction> unfinishedAuctionsList = Auction.GetAllUnfinishedAuctions();
            return (from temp in unfinishedAuctionsList
                    orderby temp.PostedDate descending
                    select temp).Take(n).ToList();
        }
        public List<Auction> GetNNextUnfinishedAuctions(int startedId, int count, bool isLess)
        {
            var auctionList = Auction.GetAllUnfinishedAuctions();
            List<Auction> result = null;
            if (auctionList.Count != 0)
            {
                if (isLess)
                {
                    result = (from temp in auctionList
                              where temp.AuctionId < startedId
                              orderby temp.PostedDate descending
                              select temp).Take(count).ToList();
                }
                else
                {
                    result = (from temp in auctionList
                              where temp.AuctionId > startedId
                              orderby temp.PostedDate descending
                              select temp).Take(count).ToList();
                }
            }
            return result;
        }
        public List<Auction> GetBeingAuctions()
        {
            return Auction.GetBeingAuctions();
        }
        public List<Auction> GetNFirstBeingAuctions(int n)
        {
            var beingAuctionsList = Auction.GetBeingAuctions();
            return (from temp in beingAuctionsList
                    orderby temp.PostedDate descending
                    select temp).Take(n).ToList();
        }
        public List<Auction> GetNNextBeingAuctions(int startedId, int count, bool isLess)
        {
            var sellAuctionList = Auction.GetBeingAuctions();
            List<Auction> result = null;
            if (sellAuctionList.Count != 0)
            {
                if (isLess)
                {
                    result = (from temp in sellAuctionList
                              where temp.AuctionId < startedId
                              orderby temp.PostedDate descending
                              select temp).Take(count).ToList();
                }
                else
                {
                    result = (from temp in sellAuctionList
                              where temp.AuctionId > startedId
                              orderby temp.PostedDate descending
                              select temp).Take(count).ToList();
                }
            }
            return result;
        }

        public List<Auction> GetAllUnfinishedBuyAuctions()
        {
            return BuyAuction.GetAllUnfinishedAuctions();
        }
        public List<Auction> GetNNewUnfinishedBuyAuctions(int n)
        {
            List<Auction> unfishedBuyAuctionsList = BuyAuction.GetAllUnfinishedAuctions();
            return (from temp in unfishedBuyAuctionsList
                    orderby temp.PostedDate descending
                    select temp).Take(n).ToList();
        }
        public List<Auction> GetNUnfinishedBuyAuctions(int startedId, int count, bool isLess)
        {
            List<Auction> buyAuctionList = BuyAuction.GetAllUnfinishedAuctions();
            List<Auction> result = null;
            if (buyAuctionList.Count != 0)
            {
                if (isLess)
                {
                    result = (from temp in buyAuctionList
                              where temp.AuctionId < startedId
                              orderby temp.PostedDate descending
                              select temp).Take(count).ToList();
                }
                else
                {
                    result = (from temp in buyAuctionList
                              where temp.AuctionId > startedId
                              orderby temp.PostedDate descending
                              select temp).Take(count).ToList();
                }
            }
            return result;
        }
        public List<Auction> GetNNewBuyAuctions(int startedId, int count)
        {
            return null;
        }
        public Auction GetAuctionById(int auctionId)
        {
            return Auction.GetAuctionById(auctionId);
        }
        public int AddNewAuction(Auction newAuction)
        {
            return Auction.AddNew(newAuction);
        }
        public int UpdateAuction(Auction updatedAuction)
        {
            return Auction.Update(updatedAuction);
        }
        public int DeleteAuction(int deletedAuctionId)
        {
            return Auction.DeleteByAuctionId(deletedAuctionId);
        }
        public List<Auctioneer> GetNNewAuctioneers(int auctionId, int n)
        {
            List<Auctioneer> allAuctioneers = Auctioneer.GetAllAuctioneersByAuctionId(auctionId);
            List<Auctioneer> temp= (from tempAuctioneer in allAuctioneers
                    orderby  tempAuctioneer.AuctioneerId descending
                    select tempAuctioneer).Take(n).ToList();
            return temp;
            
        }
        public List<Auctioneer> GetNNextAuctioneers(int auctionId,int startedAuctioneerId, int n,bool isNew)
        {
            List<Auctioneer> allAuctioneers = Auctioneer.GetAllAuctioneersByAuctionId(auctionId);
            if (isNew)
            {
                return (from tempAuctioneer in allAuctioneers
                        where tempAuctioneer.AuctioneerId > startedAuctioneerId
                        orderby tempAuctioneer.AuctioneerId descending
                        select tempAuctioneer).Take(n).ToList();
            }
            else
            {
                return (from tempAuctioneer in allAuctioneers
                        where  tempAuctioneer.AuctioneerId < startedAuctioneerId
                        orderby tempAuctioneer.AuctioneerId descending
                        select tempAuctioneer).Take(n).ToList();
            }
        }
        public int AddNewAuctioneer(Auctioneer newAuctioneer)
        {
            return Auctioneer.AddNew(newAuctioneer);
        }
        public decimal GetHighestPrice(int auctionId)
        {
            return Auctioneer.GetHighestPrice(auctionId);
        }
        public List<Auction> GetNNewUnfinishedSellAuctions(int n)
        {
            List<Auction> unfishedSellAuctionsList = SellAuction.GetAllUnfinishedAuctions();
            return (from temp in unfishedSellAuctionsList
                    orderby temp.PostedDate descending
                    select temp).Take(n).ToList();
        }
        public List<Auction> GetNUnfinishedSellAuctions(int startedId, int count, bool isLess)
        {
            List<Auction> sellAuctionList = SellAuction.GetAllUnfinishedAuctions();
            List<Auction> result = null;
            if (sellAuctionList.Count != 0)
            {
                if (isLess)
                {
                    result = (from temp in sellAuctionList
                              where temp.AuctionId < startedId
                              orderby temp.PostedDate descending
                              select temp).Take(count).ToList();
                }
                else
                {
                    result = (from temp in sellAuctionList
                              where temp.AuctionId > startedId
                              orderby temp.PostedDate descending
                              select temp).Take(count).ToList();
                }
            }
            return result;
        }
        public decimal GetLowestPrice(int auctionId)
        {
            return Auctioneer.GetLowestPrice(auctionId);
        }
        public List<TypeOfAuction> GetAllTypeOfAuction()
        {
            return TypeOfAuction.GetAllTypes();
        }
        public List<Auction> SearchForAuction(string content)
        {
            return Auction.SearchFor(content);
        }
        public List<Auctioneer> GetAllAuctioneers()
        {
            return Auctioneer.GetAllAuctioneers();
        }
        public Auctioneer GetAuctioneerById(int auctioneerId) {
            return Auctioneer.GetAuctioneerById(auctioneerId);
        }
        public bool DeleteAuctioneerById(int auctioneerId)
        {
            return Auctioneer.DeleteAuctioneerById(auctioneerId);
        }
        public int UpdateAuctioneer(Auctioneer updatedAuctioneer)
        {
            return Auctioneer.UpdateAuctioneer(updatedAuctioneer);
        }
        public List<Auction> GetBeingBuyAuctions()
        {
            return BuyAuction.GetBeingAuctions();
        }
        public List<Auction> GetBeingSellAuctions()
        {
            return SellAuction.GetBeingAuctions();
        }
        public List<Auction> GetNFirstBeingBuyAuctions(int n)
        {
            List<Auction> beingBuyAuctionsList = BuyAuction.GetBeingAuctions();
            return (from temp in beingBuyAuctionsList
                    orderby temp.PostedDate descending
                    select temp).Take(n).ToList();
        }
        public List<Auction> GetNFirstBeingSellAuctions(int n)
        {
            List<Auction> beingSellAuctionsList = SellAuction.GetBeingAuctions();
            return (from temp in beingSellAuctionsList
                    orderby temp.PostedDate descending
                    select temp).Take(n).ToList();
        }
        public List<Auction> GetNNextBeingBuyAuctions(int startedId, int count, bool isLess)
        {
            List<Auction> buyAuctionList = BuyAuction.GetBeingAuctions();
            List<Auction> result = null;
            if (buyAuctionList.Count != 0)
            {
                if (isLess)
                {
                    result = (from temp in buyAuctionList
                              where temp.AuctionId < startedId
                              orderby temp.PostedDate descending
                              select temp).Take(count).ToList();
                }
                else
                {
                    result = (from temp in buyAuctionList
                              where temp.AuctionId > startedId
                              orderby temp.PostedDate descending
                              select temp).Take(count).ToList();
                }
            }
            return result;
        }
        public List<Auction> GetNNextBeingSellAuctions(int startedId, int count, bool isLess)
        {
            List<Auction> sellAuctionList = SellAuction.GetBeingAuctions();
            List<Auction> result = null;
            if (sellAuctionList.Count != 0)
            {
                if (isLess)
                {
                    result = (from temp in sellAuctionList
                              where temp.AuctionId < startedId
                              orderby temp.PostedDate descending
                              select temp).Take(count).ToList();
                }
                else
                {
                    result = (from temp in sellAuctionList
                              where temp.AuctionId > startedId
                              orderby temp.PostedDate descending
                              select temp).Take(count).ToList();
                }
            }
            return result;
        }
        #endregion
        #region UserAndUserAccount
        public bool CheckLogIn(string userName, string password)
        {
            return UserAccount.CheckLogIn(userName, password);
        }
        public UserAccount GetUserAccountByUserName(string userName)
        {
            return UserAccount.GetUserAccountByUserName(userName);
        }
        public User GetUserByUserId(int userId)
        {
            return User.GetUser(userId);
        }
        public string GetUserImage(string userAccName)
        {
            UserAccount userAcc = GetUserAccountByUserName(userAccName);
            return UserAccount.GetImage(userAccName);
        }
        #endregion
        #region Types
        public List<TypeOfArticle> GetAllTypesOfArticle()
        {
            return TypeOfArticle.GetAllTypes();
        }
        public TypeOfArticle GetTypeOfArticlesById(int typeOfArticleId)
        {
            return TypeOfArticle.GetTypeById(typeOfArticleId);
        }

        public List<TypeOfAuction> GetAllTypesOfAuction()
        {
            return TypeOfAuction.GetAllTypes();
        }
        public TypeOfAuction GetTypeOfAuctionById(int typeOfAuctionId)
        {
            return TypeOfAuction.GetTypeById(typeOfAuctionId);
        }

        public int UpdateTypeOfAuction(TypeOfAuction updatedAuction) {
            return TypeOfAuction.UpdateTypeOfAuction(updatedAuction);
        }
        public int DeleteTypeOfAuctionById(int typeId)
        {
            return TypeOfAuction.DeleteTypeOfAuctionById(typeId);
        }
        public int AddNewTypeOfAuction(TypeOfAuction newType)
        {
            return TypeOfAuction.AddNewTypeOfAuction(newType);
        }
        public List<TypeOfProduct> GetAllTypesOfProduct()
        {
            return TypeOfProduct.GetAllTypes();
        }
        public TypeOfProduct GetTypeOfProductById(int typeOfProductId)
        {
            return TypeOfProduct.GetTypeById(typeOfProductId);
        }

        public List<Unit> GetAllUnits()
        {
            return Unit.GetAllUnits();
        }
        public Unit GetUnitById(int unitId)
        {
            return Unit.GetUnitById(unitId);
        }
        #endregion
        #region Product
        public Product GetProductById(int productId)
        {
            return Product.GetProductById(productId);
        }
        public List<Product> GetAllProducts()
        {
            return Product.GetAllProducts();
        }
        #endregion
        #region FollowedAuction
        public List<FollowedAuction> GetFollowedAuctionsByUserAccName(string userAccName) {
            return FollowedAuction.GetFollowedAuctionsByUserAccName(userAccName);
        }
        public int AddNewFollowedAuction(string userAccName, int auctionId) {
            return FollowedAuction.AddNew(new FollowedAuction(){UserAccName=userAccName,AuctionId=auctionId});
        }
        public int DeleteFollowedAuction(int deletedFaID) {
            return FollowedAuction.Delete(deletedFaID);
        }
        public FollowedAuction GetAFollowedAuctionById(int followedAuctionId)
        {
            return FollowedAuction.GetAFollowedAuctionById(followedAuctionId);
        }
        public bool DeleteFollowedAuctionsByAuctionId(int auctionId)
        {
            return FollowedAuction.DeleteFollowedAuctionsByAuctionId(auctionId);
        }
        #endregion
        #region Statistic
        public List<YProduct> GetYearStatistic(int year)
        {
            return Statistician.GetYearStatistic(year);
        }
        public  List<YProduct> GetYearStatisticInDuration(int start, int finish) {
            return Statistician.GetYearStatisticInDuration(start,finish);
        }
        #endregion
        #region SendEmail
        public bool SendEmailToAllWinners() {
            AgriMarketDataClassesDataContext db = new AgriMarketDataClassesDataContext();
            List<Tbl_Auction> finishedAuctions = (from auction in db.Tbl_Auctions
                                                  where auction.FinishedDate < DateTime.Now && ! db.Tbl_AuctionSentEmails.Any(a => a.AuctionId == auction.AuctionId) &&  db.Tbl_Auctioneers.Any(a=>a.AuctionId==auction.AuctionId)
                                                  select auction
                                               ).ToList();
            List<Tbl_Auctioneer> winners = new List<Tbl_Auctioneer>();
            foreach (var fAuction in finishedAuctions)
            {
                Tbl_Auctioneer winner = (from auctioneer in db.Tbl_Auctioneers
                                         where auctioneer.AuctionId == fAuction.AuctionId
                                         orderby auctioneer.Price descending
                                         select auctioneer).FirstOrDefault();
                if (winner != null)
                    winners.Add(winner);
            }
            List<UserAccount> userAccounts=UserAccount.GetAllUserAccounts();

            var result = (from auction in finishedAuctions
                                     join winner in winners on auction.AuctionId equals winner.AuctionId
                                     join userAcc in userAccounts on winner.AuthorId equals userAcc.UserName
                                     join userAcc1 in userAccounts on auction.AuthorId equals userAcc1.UserName
                                     select new
                                     {
                                         Auction=auction,
                                         Winner=userAcc,
                                         Poster=userAcc1
                                     }).ToList();
            List<Tbl_AuctionSentEmail> auctionSentEmail = new List<Tbl_AuctionSentEmail>();
            foreach (var item in result)
            {
                //Send to winner
                string toWinner = item.Winner.User.Email;
                string from = "anhvan02b21@gmail.com";
                string pass = "123456789abcdef";
                string body="Chúc mừng "+item.Winner.User.UserName+"!\n Bạn đã chiến thắng trong cuộc đấu giá trên AgriMarket";
                body += "\nNgười đăng: " + item.Poster.User.UserName;
                body += "\nSố điện thoại: " + item.Poster.User.Phonenumber;
                EmailSender.SendAsyncEmail(toWinner, from, pass, "Thông báo từ agrimarket", body);

                //Send to poster
                string toPoster = item.Poster.User.Email;
                string bodyPoster = "Thông báo từ AgriMarket về người thắng ở một bài đấu giá của bạn";
                bodyPoster += "\nNgười thắng: " + item.Winner.User.UserName;
                bodyPoster += "\nSố điện thoại: " + item.Winner.User.Phonenumber;
                EmailSender.SendAsyncEmail(toPoster, from, pass, "Thông báo từ agrimarket", bodyPoster);
                auctionSentEmail.Add(new Tbl_AuctionSentEmail() { AuctionId=item.Auction.AuctionId });
            }
            db.Tbl_AuctionSentEmails.InsertAllOnSubmit(auctionSentEmail);
            try
            {
                db.SubmitChanges();
                return true;
            }
            catch
            {
                return false;
            }
        }
        public List<int> SendEmailtoSomeWinners(List<int> auctionIds)
        {
            List<int> states = new List<int>();
            foreach (var auctonId in auctionIds)
            {
                states.Add(SendEmailtoAWinner(auctonId));
            }
            return states;
        }
        public int SendEmailtoAWinner(int auctionId) {
            AgriMarketDataClassesDataContext db = new AgriMarketDataClassesDataContext();
            Tbl_Auction fAuction = (from auction in db.Tbl_Auctions
                                                  where auction.AuctionId==auctionId && auction.FinishedDate < DateTime.Now && !db.Tbl_AuctionSentEmails.Any(a => a.AuctionId == auction.AuctionId)
                                                  select auction
                                               ).FirstOrDefault();
            if (fAuction == null)
                return 1;//Sent already Or Unfinished
            Tbl_Auctioneer auctioneer = (from tempauctioneer in db.Tbl_Auctioneers
                                         where tempauctioneer.AuctionId == fAuction.AuctionId
                                         orderby tempauctioneer.Price descending
                                         select tempauctioneer).FirstOrDefault();
            if (auctioneer == null)
                return 2;//No found winner

            UserAccount winner = UserAccount.GetUserAccountByUserName(auctioneer.AuthorId);
            UserAccount poster = UserAccount.GetUserAccountByUserName(fAuction.AuthorId);

            //Send to winner
            string toWinner = winner.User.Email;
            string from = "anhvan02b21@gmail.com";
            string pass = "123456789abcdef";
            string body = "Chúc mừng " + winner.User.UserName + "!\n Bạn đã chiến thắng trong cuộc đấu giá trên AgriMarket";
            body += "\nNgười đăng: " + poster.User.UserName;
            body += "\nSố điện thoại: " + poster.User.Phonenumber;
            EmailSender.SendAsyncEmail(toWinner, from, pass, "Thông báo từ agrimarket", body);
            //Send to poster
            string toPoster = poster.User.Email;
            string bodyPoster = "Thông báo từ AgriMarket về người thắng ở một bài đấu giá của bạn";
            bodyPoster += "\nNgười thắng: " + poster.User.UserName;
            bodyPoster += "\nSố điện thoại: " + poster.User.Phonenumber;
            EmailSender.SendAsyncEmail(toPoster, from, pass, "Thông báo từ agrimarket", bodyPoster);

            Tbl_AuctionSentEmail auctionSentEmail = new Tbl_AuctionSentEmail() { AuctionId = auctionId };
            db.Tbl_AuctionSentEmails.InsertOnSubmit(auctionSentEmail);
            try
            {
                db.SubmitChanges();
                return 0;
            }
            catch
            {
                return 1;//error
            }
        }
        public List<Auction> GetUnSentAuctions()
        {
            return Auction.GetUnSentAuctions();
        }
        #endregion
    }
}